package com.gzc.just.play.last.war.sceneserver.benchmark;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Random;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * 伤害计算性能基准测试
 * 
 * 测试目标:
 * - 基础伤害计算: 10,000 ops/sec
 * - 平均延迟: < 100μs
 * - 99% 延迟: < 500μs
 */
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 1)
public class DamageCalculatorBenchmark {
    
    private Random random = new Random();
    private int baseDamage = 100;
    private int attackerLevel = 50;
    private int targetLevel = 50;
    private int attackPower = 300;
    private int defense = 150;
    private float criticalChance = 0.25f;
    private float criticalMultiplier = 2.0f;
    private float dodgeChance = 0.15f;
    private float armorReduction = 0.1f;
    
    @Benchmark
    public int benchmarkBasicDamageCalculation() {
        // 基础伤害计算
        return baseDamage + random.nextInt(50);
    }
    
    @Benchmark
    public int benchmarkDamageCalculationWithAttributes() {
        // 带属性的伤害计算
        return baseDamage + (attackPower / 10) + (attackerLevel - targetLevel) * 2;
    }
    
    @Benchmark
    public int benchmarkCriticalDamageCalculation() {
        // 暴击伤害计算
        int damage = baseDamage + (attackPower / 10);
        if (random.nextFloat() < criticalChance) {
            damage = (int) (damage * criticalMultiplier);
        }
        return damage;
    }
    
    @Benchmark
    public boolean benchmarkDodgeCalculation() {
        // 闪避计算
        return random.nextFloat() >= dodgeChance;
    }
    
    @Benchmark
    public int benchmarkArmorReduction() {
        // 护甲减伤计算
        int damage = baseDamage + (attackPower / 10);
        int reducedDamage = damage - defense;
        if (reducedDamage < 0) reducedDamage = 1;
        
        // 应用护甲减免
        return (int) (reducedDamage * (1.0f - armorReduction));
    }
    
    @Benchmark
    public int benchmarkComplexDamageCalculation() {
        // 复杂伤害计算（全因素）
        int damage = baseDamage + (attackPower / 10) + (attackerLevel - targetLevel) * 2;
        
        // 暴击判定
        if (random.nextFloat() < criticalChance) {
            damage = (int) (damage * criticalMultiplier);
        }
        
        // 护甲减伤
        int reducedDamage = damage - defense;
        if (reducedDamage < 0) reducedDamage = 1;
        damage = (int) (reducedDamage * (1.0f - armorReduction));
        
        // 随机浮动
        damage += random.nextInt(20) - 10; // -10 到 +10
        
        return Math.max(1, damage);
    }
    
    @Benchmark
    public int[] benchmarkBulkDamageCalculation() {
        // 批量伤害计算
        int[] results = new int[10];
        for (int i = 0; i < 10; i++) {
            results[i] = benchmarkComplexDamageCalculation();
        }
        return results;
    }
    
    /**
     * JUnit 测试方法 - 验证基准测试是否可以正常工作
     */
    @Test
    public void testDamageCalculationSetup() {
        // 测试设置是否正确
        assertTrue(baseDamage > 0, "Base damage should be positive");
        assertTrue(attackPower > 0, "Attack power should be positive");
        assertTrue(defense >= 0, "Defense should be non-negative");
        
        // 测试方法可以正常运行
        int result = benchmarkBasicDamageCalculation();
        assertTrue(result > 0, "Damage calculation should return positive value");
        
        result = benchmarkComplexDamageCalculation();
        assertTrue(result > 0, "Complex damage calculation should return positive value");
    }
    
    /**
     * JUnit 测试方法 - 验证基准测试方法的性能
     */
    @Test
    public void testDamageCalculationPerformance() {
        // 测试基础性能
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            benchmarkBasicDamageCalculation();
        }
        long duration = System.nanoTime() - startTime;
        
        // 验证在合理时间内完成（1秒内）
        assertTrue(duration < 1_000_000_000L, 
            "Basic damage calculation should complete within 1 second");
        
        // 测试复杂计算性能
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            benchmarkComplexDamageCalculation();
        }
        duration = System.nanoTime() - startTime;
        
        // 验证在合理时间内完成（2秒内）
        assertTrue(duration < 2_000_000_000L, 
            "Complex damage calculation should complete within 2 seconds");
    }
}